#pragma once

#include "common.h"

namespace Client
{
    using namespace std;

    enum
    {
        USAGE_ERROR = 1,
        SOCKET_ERROR = 2,
        BIND_ERROR = 3
    };

    using func_t = function<void(int)>;

    class udpClient
    {
    public:

        udpClient(const uint16_t& port, const string& ip, func_t callback) 
            : _sockfd(-1), _server_port(port), _server_ip(ip), _quit(false), _callback(callback)
        {}


        void init()
        {
            _sockfd = socket(AF_INET, SOCK_DGRAM, 0);
            if (_sockfd == -1)
            {
                cerr << "socket error: " << errno << " : " << strerror(errno) << endl;
                exit(SOCKET_ERROR);
            }
        }

        static void* recvhander(void* args)
        {
            udpClient *_this = static_cast<udpClient *>(args);
            int sockfd = _this->_sockfd;
            pthread_detach(pthread_self());
            
            while (true)
            {
                _this->_callback(sockfd);
            }
        }

        void run()
        {
            pthread_create(&_recvthread, nullptr, recvhander, (void *)this);

            struct sockaddr_in target;
            bzero(&target, sizeof(target));
            target.sin_family = AF_INET;
            target.sin_port = htons(_server_port);
            target.sin_addr.s_addr = inet_addr(_server_ip.c_str());

            string masage;
            while (!_quit)
            {
                fprintf(stderr, "请输入>:");
                fflush(stderr);

                getline(cin, masage);

                sendto(_sockfd, masage.c_str(), masage.size(), 0, (struct sockaddr*)&target, sizeof(target));
            }
        }

    private:
        int _sockfd;
        uint16_t _server_port;
        string _server_ip;
        func_t _callback;
        bool _quit;

        pthread_t _recvthread;
    };
}